home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / vol7n2.arc / PUTENV.ASM < prev    next >
Assembly Source File  |  1987-12-23  |  7KB  |  186 lines

  1.         name    putenv
  2.         page    55,132
  3.         title   PUTENV modify environment variable
  4. ;
  5. ; PUTENV.ASM --- add or modify environment variable
  6. ;
  7. ; (C) 1987 Ziff Communications Co, by Ray Duncan
  8. ;
  9. ; Call with:    DS:SI = new ASCIIZ environment variable 
  10. ;               ES    = segment of program segment prefix
  11. ;
  12. ; Returns:      AX    = 0 if successful, -1 if failed
  13.  
  14. DGROUP  group   _DATA
  15.  
  16. _TEXT   segment word public 'CODE'
  17.  
  18.         assume  cs:_TEXT
  19.  
  20.         public  putenv          ; make visible to Linker
  21.  
  22.         extrn   getenv:near
  23.  
  24.                                 ; names for working storage
  25. oldenv  equ     [bp-2]          ; segment of old environment
  26. envlen  equ     [bp-4]          ; length of old environment
  27. newenv  equ     [bp-6]          ; segment of new environment
  28. pspseg  equ     [bp-8]          ; segment of program segment prefix
  29. oldlen  equ     [bp-10]         ; length of existing variable
  30. newlen  equ     [bp-12]         ; length of new env. variable
  31. newname equ     [bp-14]         ; offset of new name portion
  32. newvar  equ     [bp-16]         ; offset of new param. portion
  33.  
  34. putenv  proc    near            ; modify/add environment variable
  35.  
  36.         push    bp              ; set up stack frame for
  37.         mov     bp,sp           ;  working storage
  38.         sub     sp,16
  39.  
  40.         mov     newname,si      ; save offset of new variable
  41.         mov     pspseg,es       ; save PSP segment
  42.         mov     es,es:[002ch]   ; pick up segment of old 
  43.         mov     oldenv,es       ;  environment and save it
  44.  
  45.         push    cx              ; save other registers
  46.         push    si
  47.         push    di
  48.         
  49.                                 ; find old environment length
  50.         mov     cx,8000h        ; assume max = 32 KBytes
  51.         xor     di,di           ; ES:DI = environment base
  52.         xor     al,al
  53. put1:   repne scasb             ; scan for double null (can't use
  54.         scasb                   ; SCASW since might be on odd addr)
  55.         jne     put1
  56.  
  57.         mov     envlen,di       ; save length of old environment
  58.  
  59.         mov     di,si           ; find length of new env. variable
  60.         mov     ax,ds           ; ES:DI = addr of new variable  
  61.         mov     es,ax
  62.         mov     cx,-1
  63.         xor     al,al
  64.         repne scasb             ; scan for terminating null byte
  65.         not     cx              ; now CX = length including null
  66.         mov     newlen,cx       ; save length of new variable
  67.  
  68.                                 ; attempt to allocate memory
  69.                                 ; block for new environment...  
  70.         mov     bx,cx           ; length of old environment
  71.         add     bx,envlen       ; + length of new variable
  72.         mov     cl,4            ; divide by 16 and round
  73.         shr     bx,cl           ; up to find paragraphs to 
  74.         inc     bx              ; allocate for new environment
  75.         mov     ah,48h          ; Fxn 48h=allocate memory block
  76.         int     21h             ; transfer to MS-DOS
  77.         jnc     put2            ; jump if allocation succeeded
  78.  
  79.         mov     ax,-1           ; otherwise, return error flag
  80.         jmp     put6
  81.  
  82. put2:   mov     newenv,ax       ; save new environment segment
  83.  
  84.         mov     di,offset envar ; copy name portion of new 
  85.                                 ; variable to local storage
  86.  
  87. put3:   movsb                   ; copy characters up to '='
  88.         cmp     byte ptr [si],'='
  89.         jne     put3            ; loop until end of name found
  90.         xor     al,al           ; append null byte to name
  91.         stosb
  92.  
  93.         inc     si              ; save address of param.
  94.         mov     newvar,si       ; portion of new variable
  95.  
  96.         mov     si,offset envar ; check if new environment 
  97.         mov     es,oldenv       ; variable has a previous value
  98.         call    getenv          ; in old environment
  99.         mov     oldlen,ax       ; save length of value, if any
  100.  
  101.         or      ax,ax           ; was it present in old block?
  102.         jnz     put4            ; yes, PUTENV the hard way
  103.  
  104.         push    ds              ; no just copy existing environment
  105.                                 ; and add the new variable
  106.  
  107.         mov     ds,oldenv       ; DS:SI = old env. block
  108.         mov     es,newenv       ; ES:DI = new env. block
  109.         mov     cx,envlen       ; CX = length of old environment 
  110.         dec     cx              ; less the extra null byte
  111.         xor     si,si
  112.         xor     di,di
  113.         rep movsb               ; copy the old stuff
  114.  
  115.         pop     ds              ; DS:SI = address of new variable 
  116.         mov     si,newname      ; ES:DI = end of new environment
  117.         mov     cx,newlen       ; CX = length of new variable
  118.         rep movsb               ; append the new variable
  119.         xor     al,al           ; and the extra null byte
  120.         stosb                   ; marking end of environment
  121.         jmp     put5            ; go update PSP env. pointer
  122.  
  123. put4:                           ; come here on the messy case,
  124.                                 ; env. variable already exists
  125.                                 ; ES:DI = offset+1 of '=' in
  126.                                 ; old variable from 'getenv'
  127.  
  128.         push    ds              ; copy old environment to new
  129.         mov     ax,es           ; up through the '=' of the
  130.         mov     ds,ax           ; variable we are changing
  131.         mov     cx,di           ; DS:SI = old environment
  132.         mov     es,newenv       ; ES:DI = new environment
  133.         xor     si,si           ; CX = offset+1 of '=' 
  134.         xor     di,di           ;      in old variable
  135.         rep movsb
  136.  
  137.         pop     ds              ; now let DS:SI = offset+1 
  138.         push    si              ; of '=' in new variable
  139.         mov     si,newvar       ; and CX = length of portion
  140.         mov     cx,newname      ; following the '='
  141.         add     cx,newlen
  142.         sub     cx,newvar       ; copy the new parameter portion
  143.         rep movsb               ; to the new environment
  144.  
  145.         pop     si              ; skip over parameter portion
  146.         add     si,oldlen       ; of the old variable
  147.         inc     si              ; and its null byte
  148.  
  149.         push    ds              ; now copy remainder of
  150.         mov     ds,oldenv       ; old environment to new one
  151.         mov     cx,envlen       ; total length less portion
  152.         sub     cx,si           ; already copied and length
  153.         rep movsb               ; of old environment variable
  154.         pop     ds
  155.  
  156. put5:                           ; PUTENV function successful,
  157.         mov     es,oldenv       ; release old environment block
  158.         mov     ah,49h
  159.         int     21h             ; transfer to MS-DOS
  160.  
  161.         mov     es,pspseg       ; update pointer to new 
  162.         mov     ax,newenv       ; environment in caller's PSP
  163.         mov     es:[002ch],ax
  164.  
  165.         xor     ax,ax           ; return success code
  166.  
  167. put6:   pop     di              ; restore registers
  168.         pop     si
  169.         pop     cx
  170.         mov     sp,bp           ; discard stack frame
  171.         pop     bp
  172.         ret                     ; back to caller
  173.  
  174. putenv  endp
  175.  
  176. _TEXT   ends
  177.  
  178.  
  179. _DATA   segment word public 'DATA'
  180.  
  181. envar   db      80 dup (0)      ; name of new environment var.
  182.                                 ; for call to 'getenv'
  183. _DATA   ends
  184.  
  185.         end
  186.